java模板字符串优雅解析(占位符解析) 您所在的位置:网站首页 java 字符串模版 java模板字符串优雅解析(占位符解析)

java模板字符串优雅解析(占位符解析)

2024-06-17 11:21| 来源: 网络整理| 查看: 265

项目中常常需要解析字符串模板,比如user:{userId}:{userType}用于redis的key等,比较常见的做法就是使用String.format("user:%s:%s", 1, 1)方法,但个人感觉那样的模板不够明了,而使用模板解析器可更好地有助于解析此类字符串。可使用map用于解析,也可使用对象进行解析,也可使用类似String.format可变参数进行解析,多样化解析对象值。有点类似于js的模板字符串${}。 也可自定义前缀后缀进行解析。如PlaceholderResolver.getResolver("{", "}")该对象可解析{}该类型的占位符. 性能方面: PlaceholderResolve解析结果 String.format解析结果

解析100w次,占位符解析比String.format平均都会快个0.4~0.5s,so 性能应该问题不大。最主要的是不需要调用太多的对象方法,自动解析,方便快捷。

源代码如下: /** * 占位符解析器 * * @author meilin.huang * @version 1.0 * @date 2018-11-13 1:42 PM */ public class PlaceholderResolver { /** * 默认前缀占位符 */ public static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; /** * 默认后缀占位符 */ public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; /** * 默认单例解析器 */ private static PlaceholderResolver defaultResolver = new PlaceholderResolver(); /** * 占位符前缀 */ private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX; /** * 占位符后缀 */ private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX; private PlaceholderResolver(){} private PlaceholderResolver(String placeholderPrefix, String placeholderSuffix) { this.placeholderPrefix = placeholderPrefix; this.placeholderSuffix = placeholderSuffix; } /** * 获取默认的占位符解析器,即占位符前缀为"${", 后缀为"}" * @return */ public static PlaceholderResolver getDefaultResolver() { return defaultResolver; } public static PlaceholderResolver getResolver(String placeholderPrefix, String placeholderSuffix) { return new PlaceholderResolver(placeholderPrefix, placeholderSuffix); } /** * 解析带有指定占位符的模板字符串,默认占位符为前缀:${ 后缀:} * 如:template = category:${}:product:${} * values = {"1", "2"} * 返回 category:1:product:2 * * @param content 要解析的带有占位符的模板字符串 * @param values 按照模板占位符索引位置设置对应的值 * @return */ public String resolve(String content, String... values) { int start = content.indexOf(this.placeholderPrefix); if (start == -1) { return content; } //值索引 int valueIndex = 0; StringBuilder result = new StringBuilder(content); while (start != -1) { int end = result.indexOf(this.placeholderSuffix); String replaceContent = values[valueIndex++]; result.replace(start, end + this.placeholderSuffix.length(), replaceContent); start = result.indexOf(this.placeholderPrefix, start + replaceContent.length()); } return result.toString(); } /** * 解析带有指定占位符的模板字符串,默认占位符为前缀:${ 后缀:} * 如:template = category:${}:product:${} * values = {"1", "2"} * 返回 category:1:product:2 * * @param content 要解析的带有占位符的模板字符串 * @param values 按照模板占位符索引位置设置对应的值 * @return */ public String resolve(String content, Object[] values) { return resolve(content, Stream.of(values).map(String::valueOf).toArray(String[]::new)); } /** * 根据替换规则来替换指定模板中的占位符值 * @param content 要解析的字符串 * @param rule 解析规则回调 * @return */ public String resolveByRule(String content, Function rule) { int start = content.indexOf(this.placeholderPrefix); if (start == -1) { return content; } StringBuilder result = new StringBuilder(content); while (start != -1) { int end = result.indexOf(this.placeholderSuffix, start); //获取占位符属性值,如${id}, 即获取id String placeholder = result.substring(start + this.placeholderPrefix.length(), end); //替换整个占位符内容,即将${id}值替换为替换规则回调中的内容 String replaceContent = placeholder.trim().isEmpty() ? "" : rule.apply(placeholder); result.replace(start, end + this.placeholderSuffix.length(), replaceContent); start = result.indexOf(this.placeholderPrefix, start + replaceContent.length()); } return result.toString(); } /** * 替换模板中占位符内容,占位符的内容即为map key对应的值,key为占位符中的内容。 * 如:content = product:${id}:detail:${did} * valueMap = id -> 1; pid -> 2 * 经过解析返回 product:1:detail:2 * * @param content 模板内容。 * @param valueMap 值映射 * @return 替换完成后的字符串。 */ public String resolveByMap(String content, final Map valueMap) { return resolveByRule(content, placeholderValue -> String.valueOf(valueMap.get(placeholderValue))); } /** * 根据properties文件替换占位符内容 * @param content * @param properties * @return */ public String resolveByProperties(String content, final Properties properties) { return resolveByRule(content, placeholderValue -> properties.getProperty(placeholderValue)); } /** * 根据对象中字段路径(即类似js访问对象属性值)替换模板中的占位符 * 如 content = product:${id}:detail:${detail.id} * obj = Product.builder().id(1).detail(Detail.builder().id(2).build()).build(); * 经过解析返回 product:1:detail:2 * * @param content 要解析的内容 * @param obj 填充解析内容的对象(如果是基本类型,则所有占位符替换为相同的值) * @return */ public String resolveByObject(String content, final Object obj) { if (obj instanceof Map) { return resolveByMap(content, (Map)obj); } return resolveByRule(content, placeholderValue -> String.valueOf(ReflectionUtils.getValueByFieldPath(obj, placeholderValue))); } } 由于代码还有一些工具类的调用因为篇幅问题没有贴,如有需要可以去 https://gitee.com/objs/mayfly 该项目中获取


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有